/*
 * Copyright (C) 2021 The Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.oushangfeng.pinnedsectionitemdecoration.callback.move;

import com.oushangfeng.pinnedsectionitemdecoration.callback.datainterface.Category;
import com.oushangfeng.pinnedsectionitemdecoration.callback.datainterface.Model;

import ohos.agp.components.Component;
import ohos.agp.components.Image;
import ohos.agp.components.ListContainer;
import ohos.agp.components.Text;

import java.util.List;

/**
 * 测量悬停标签与滑动标签的距离并进行移动
 *
 * @since 2021-03-27
 */
public class MoveMethod {
    /**
     * 表示线性布局
     */
    public static final int LINEARLAYOUT = 1;

    /**
     * 表示网格布局
     */
    public static final int GRIDELAYOUT = 2;

    /**
     * 表示瀑布流布局
     */
    public static final int STAGGEREDGRIDKAYOUT = 3;

    /**
     * 表示股价
     */
    public static final int SHAREDLAYOUT = 4;

    /**
     * 表示小标签布局
     */
    public static final int LITTLETITLELAYOUT = 5;

    /**
     * 表示类型为标题
     */
    public static final int HEADITEM_ITEM_TYPE = 0;
    private static final int MINDISTANCE = 10;
    private static final int NEGATIVEONT = -1000;
    private static final int TWO = 2;
    private static final int TWENTYFIVE = 25;

    // 记录布局
    private int layoutId = LINEARLAYOUT;

    private ListContainer listContainer;
    private List<Category> categoryList;
    private List<Category> cacheCategoryList;
    private List<Model> cacheModels;
    private List<Model> models;
    private float mShowTextY = 0;
    private float mTitleBarY = 0;

    private float mOldShowTextY = NEGATIVEONT;

    private Image mShowHeaderItemImage;

    private Text mShowHeaderItemContentText;

    // 下滑时是否要更改上方悬停标题
    private boolean isChangeTitle = false;

    // 缓存被更改的原标签值
    private String cacheTitle = "Dog";

    // 缓存被更改的原标签的数组下标
    private int cacheShowListNum = 0;

    // 缓存被更改下标的原数组的具体值的下标
    private int cacheShowList = 1;

    // 缓存刷新的数据源的下标
    private int cacheIndex = 0;

    // 标记  刷新数据源
    private boolean isNotify = true;

    // 判断上滑是否回弹
    private boolean isScroll = false;

    private String mLittleItem = "Dog";

    private int listSize;

    private int littleSize;

    /**
     * MoveMethod构造方法
     *
     * @param listContainer
     * @param pinText
     * @param pinImage
     */
    public MoveMethod(ListContainer listContainer, Text pinText, Image pinImage) {
        this.listContainer = listContainer;
        this.mShowHeaderItemContentText = pinText;
        this.mShowHeaderItemImage = pinImage;
    }

    public void setCacheTitle(String cacheTitle) {
        this.cacheTitle = cacheTitle;
    }

    public void setLayoutId(int layoutId) {
        this.layoutId = layoutId;
    }

    public int getLayoutId() {
        return layoutId;
    }

    public void setListDatas(List<Category> list) {
        this.categoryList = list;
    }

    public void setCacheListDatas(List<Category> list) {
        this.cacheCategoryList = list;
    }

    public void setListModels(List<Model> list) {
        this.models = list;
    }

    public void setCacheListModels(List<Model> list) {
        this.cacheModels = list;
    }

    public List<Category> getCategoryListDatas() {
        return categoryList;
    }

    public List<Category> getCacheCategoryListDatas() {
        return cacheCategoryList;
    }

    public List<Model> getModels() {
        return models;
    }

    public List<Model> getCacheModels() {
        return cacheModels;
    }

    /**
     * 获取到小标签数据源的大小
     *
     * @return 返回小标签的大小
     */
    public String getmLittleItem() {
        return mLittleItem;
    }

    /**
     * 悬停标题更改文本
     *
     * @param text
     */
    public void setText(String text) {
        mShowHeaderItemContentText.setText(text);
    }

    public String getText() {
        return mShowHeaderItemContentText.getText();
    }

    /**
     * 小标签悬停图片更改
     *
     * @param resId
     */
    public void setPixelMap(int resId) {
        mShowHeaderItemImage.setPixelMap(resId);
    }

    /**
     * 上滑方法的测量和移动
     */
    public void upMove() {
        // 获取当前屏幕完整显示的第0个item的下标
        int index = listContainer.getItemPosByVisibleIndex(0);

        if (index != 0) {
            // 当前展示的列表的下标
            int mShowList = getListItem(index);
            int mLittleShowList = getLittleListItem(index);

            // 当前展示的列表的元素的下标
            int mShowListNum = getListNum(index);

            int mLittleShowListNum = getLittleListNum(index);

            int mLaterType = 0;
            if (layoutId == LINEARLAYOUT) {
                mLaterType = categoryList.get(mShowList).getCategoryItemType(mShowListNum);
            } else if (layoutId == GRIDELAYOUT || layoutId == STAGGEREDGRIDKAYOUT) {
                mLaterType = models.get(index).getItemType();
            } else if (layoutId == LITTLETITLELAYOUT) {
                mLaterType = categoryList.get(mLittleShowList).getCategoryItemType(mLittleShowListNum);
            }

            Component mFirstComponent = listContainer.getComponentAt(index);

            // 当前第一个为Haed类型
            if (mLaterType == HEADITEM_ITEM_TYPE) {
                lableNumChange(index, mFirstComponent);
            } else {
                if (layoutId == LINEARLAYOUT || layoutId == GRIDELAYOUT || layoutId == STAGGEREDGRIDKAYOUT) {
                    mShowHeaderItemContentText.setContentPositionY(mOldShowTextY);
                } else if (layoutId == LITTLETITLELAYOUT) {
                    mShowHeaderItemImage.setContentPositionY(mOldShowTextY);
                }

                if (index > 0) {
                    monitorFrontLabel(index);
                }
            }
        }
    }

    private void monitorFrontLabel(int index) {
        int index1 = index + 1;

        // 当前展示的列表的下标
        int mShowList1 = getListItem(index1);

        int mLittleShowList1 = getLittleListItem(index1);

        // 当前展示的列表的元素的下标
        int mShowListNum1 = getListNum(index1);
        int mLittleShowListNum1 = getLittleListNum(index1);

        int mLaterType1 = 0;
        if (layoutId == LINEARLAYOUT) {
            mLaterType1 = categoryList.get(mShowList1).getCategoryItemType(mShowListNum1);
        } else if (layoutId == GRIDELAYOUT || layoutId == STAGGEREDGRIDKAYOUT) {
            mLaterType1 = models.get(index1).getItemType();
        } else if (layoutId == LITTLETITLELAYOUT) {
            mLaterType1 = categoryList
                    .get(mLittleShowList1)
                    .getCategoryItemType(mLittleShowListNum1);
        }

        if (HEADITEM_ITEM_TYPE == mLaterType1) {
            labelNumReduction(index);
        }
    }

    private void labelNumReduction(int index) {
        if (isScroll) {
            isScroll = false;

            // 标签值还原
            if (layoutId == LINEARLAYOUT || layoutId == LITTLETITLELAYOUT) {
                String itemVaule = cacheCategoryList.get(cacheShowList).getItemVaule(0);
                categoryList.get(cacheShowList).setItemVaule(cacheShowListNum, itemVaule);
                listContainer.getItemProvider().notifyDataSetItemChanged(cacheIndex);
                if (layoutId == LINEARLAYOUT) {
                    listContainer.scrollTo(0, mShowHeaderItemContentText.getHeight());
                    String vaule = cacheCategoryList.get(getListItem(index)).getItemVaule(0);
                    setText(vaule);
                } else if (layoutId == LITTLETITLELAYOUT) {
                    labelInfo();
                }
            } else if (layoutId == GRIDELAYOUT || layoutId == STAGGEREDGRIDKAYOUT) {
                //  !!!!!!
                // 重复赋值  models与cacheModels一致  未改变

                models.get(index + 1).setItemValue(cacheModels.get(index + 1).getItemValue());
                listContainer.getItemProvider().notifyDataSetItemChanged(index + 1);

                // cacheTitle为不理想值
                setText(cacheTitle);
            }
            isNotify = true;
        }
    }

    private void labelInfo() {
        if (cacheShowList > 0) {
            mLittleItem = cacheCategoryList.get(cacheShowList - 1).getItemName(cacheShowListNum);
        } else {
            mLittleItem = cacheCategoryList.get(cacheShowList).getItemName(cacheShowListNum);
        }
        listContainer.scrollTo(0, mShowHeaderItemImage.getHeight());
        mShowHeaderItemImage.setPixelMap(Integer.parseInt(cacheTitle));
    }

    // 当第一个标题类型为Head时
    private void lableNumChange(int index, Component firstcomponent) {
        // 当前展示的列表的下标
        int mShowList = getListItem(index);

        int mLittleShowList = getLittleListItem(index);

        // 当前展示的列表的元素的下标
        int mShowListNum = getListNum(index);

        int mLittleShowListNum = getLittleListNum(index);

        if (isNotify) {
            // 将标签的值设置为上一个标签的值
            // lastValue相当于Dog
            if (layoutId == LINEARLAYOUT) {
                categoryList.get(mShowList).setItemVaule(mShowListNum,
                        categoryList.get(mShowList - 1).getItemVaule(mShowListNum));
                listContainer.getItemProvider().notifyDataSetItemChanged(index);

                // 缓存更改的item下标
                cacheShowList = mShowList;
                cacheShowListNum = mShowListNum;
                cacheIndex = index;
            } else if (layoutId == GRIDELAYOUT || layoutId == STAGGEREDGRIDKAYOUT) {
                cacheTitle = models.get(index - TWO).getItemValue();
                models.get(index).setItemValue(cacheTitle);
                listContainer.getItemProvider().notifyDataSetItemChanged(index);

                // 缓存更改的item下标
                cacheShowList = mShowList;
                cacheShowListNum = mShowListNum;
                cacheIndex = index;
            } else if (layoutId == LITTLETITLELAYOUT) {
                cacheTitle = categoryList.get(mLittleShowList - 1).getItemVaule(mLittleShowListNum);
                categoryList.get(mLittleShowList).setItemVaule(mLittleShowListNum, cacheTitle);
                listContainer.getItemProvider().notifyDataSetItemChanged(index);

                // 缓存更改的item下标
                cacheShowList = mLittleShowList;
                cacheShowListNum = mLittleShowListNum;
                cacheIndex = index;
            }
            isNotify = false;
        }
        isScroll = true;

        if (firstcomponent != null) {
            if (layoutId == LINEARLAYOUT || layoutId == GRIDELAYOUT || layoutId == STAGGEREDGRIDKAYOUT) {
                mShowHeaderItemContentText.setContentPositionY(
                        (float) ((double)firstcomponent.getContentPositionY() + (double) firstcomponent.getHeight() * TWO));
            } else if (layoutId == LITTLETITLELAYOUT) {
                double mLittleDistance = (double)firstcomponent.getContentPositionY() + (double)firstcomponent.getHeight();
                mShowHeaderItemImage.setContentPositionY((float) mLittleDistance);
            }
        }
    }

    /**
     * 下滑方法的测量和移动
     */
    public void downMove() {
        if (mOldShowTextY == NEGATIVEONT) {
            if (layoutId == LITTLETITLELAYOUT) {
                mOldShowTextY = mShowHeaderItemImage.getContentPositionY();
            } else {
                mOldShowTextY = mShowHeaderItemContentText.getContentPositionY();
            }
        }

        // 获取当前屏幕完整显示的第1个item的下标
        int index = listContainer.getItemPosByVisibleIndex(1);

        // 当前展示的列表的下标
        int mShowList = getListItem(index);
        int mLittleShowList = getLittleListItem(index);

        // 当前展示的列表的元素的下标
        int mShowListNum = getListNum(index);
        int mLittleShowListNum = getLittleListNum(index);

        int mNowType = 0;
        if (layoutId == LINEARLAYOUT) {
            mNowType = categoryList.get(mShowList).getCategoryItemType(mShowListNum);
        } else if (layoutId == GRIDELAYOUT || layoutId == STAGGEREDGRIDKAYOUT) {
            mNowType = models.get(index).getItemType();
        } else if (layoutId == LITTLETITLELAYOUT) {
            // 小标签图片id small_label_icon
            mNowType = categoryList.get(mLittleShowList).getCategoryItemType(mLittleShowListNum);
        }

        if (mNowType == HEADITEM_ITEM_TYPE) {
            downLabelChange(index);
        } else {
            if (layoutId == LITTLETITLELAYOUT) {
                mShowHeaderItemImage.setContentPositionY(mOldShowTextY);
            } else {
                mShowHeaderItemContentText.setContentPositionY(mOldShowTextY);
            }
            if (isChangeTitle && index != 0) {
                if (layoutId == LINEARLAYOUT) {
                    cacheTitle = mShowHeaderItemContentText.getText();
                    setText(cacheCategoryList.get(mShowList).getItemVaule(0));
                } else if (layoutId == GRIDELAYOUT || layoutId == STAGGEREDGRIDKAYOUT) {
                    cacheTitle = mShowHeaderItemContentText.getText();
                    setText(cacheModels.get(index - 1).getItemValue());
                } else if (layoutId == LITTLETITLELAYOUT) {
                    mLittleItem = cacheCategoryList.get(mLittleShowList).getItemName(mLittleShowListNum);
                    mShowHeaderItemImage.setPixelMap(Integer.parseInt(
                            cacheCategoryList.get(mLittleShowList).getItemVaule(0)));
                }
                isChangeTitle = false;
            }
        }
    }

    private void downLabelChange(int index) {
        isChangeTitle = true;

        // 当第一个显示的是标题栏的话就记录Y轴位置
        Component mFirstComponent;
        mFirstComponent = listContainer.getComponentAt(index);

        // 记录上方展示的Text的下Y轴值
        float mShowTextOldY = 0;
        if (layoutId == LITTLETITLELAYOUT) {
            mShowTextOldY = mShowHeaderItemImage.getHeight();
        } else {
            mShowTextOldY = mShowHeaderItemContentText.getHeight();
        }

        // 下方滑上来之后中间的间隙在于show_text_old_Y的值  后续需调试  请注意
        // 记录标题栏的上Y轴值
        int mFirstComponentTop = mFirstComponent.getTop();

        // 如果最上方展示text的下Y轴对应上滑上来的标题栏的上Y轴就记录位置
        if ((double)mShowTextOldY - (double) mFirstComponentTop < MINDISTANCE) {
            mShowTextY = mShowTextOldY;
            mTitleBarY = mFirstComponentTop;
        }

        // 如果展示的text的下Y轴大于标题栏的上Y轴就让展示的text的Y轴移动
        if (layoutId == LINEARLAYOUT || layoutId == GRIDELAYOUT || layoutId == STAGGEREDGRIDKAYOUT) {
            if (mFirstComponentTop < mShowTextY) {
                float mTitleBarDifferenceY = (float) ((double)mTitleBarY - (double) mFirstComponentTop);
                mShowHeaderItemContentText.setContentPositionY((float) ((double)mShowTextY - (double) mTitleBarDifferenceY + (double) TWENTYFIVE));
            }
        } else if (layoutId == LITTLETITLELAYOUT) {
            if ((double)mShowTextY + (double) mShowHeaderItemImage.getHeight() * (double) TWO > mFirstComponentTop) {
                double mTitleBarDifferenceY = (double)mTitleBarY - (double) mFirstComponentTop;
                mShowHeaderItemImage.setContentPositionY((float) ((double)mShowTextY - mTitleBarDifferenceY + TWENTYFIVE));
            }
        }
    }

    public void setListSize(int listSize) {
        this.listSize = listSize;
    }

    public void setLittleSize(int littleSize) {
        this.littleSize = littleSize;
    }

    /**
     * 获取线性的集合的下标
     *
     * @param index
     * @return 线性集合下标
     */
    public int getListNum(int index) {
        return index % listSize;
    }

    /**
     * 获取小标签的集合的下标
     *
     * @param index
     * @return 小标签集合下标
     */
    public int getLittleListNum(int index) {
        return index % littleSize;
    }

    /**
     * 获取线性的集合的集合的下标
     *
     * @param index
     * @return 集合的集合下标
     */
    public int getListItem(int index) {
        return index / listSize;
    }

    /**
     * 获取小标签的集合的集合的下标
     *
     * @param index
     * @return 小标签的集合的集合下标
     */
    public int getLittleListItem(int index) {
        return index / littleSize;
    }
}
